#include "wfimporter.h"
#include <stdio.h>
#include <stdlib.h>
#include <QLinkedList>
#include "amutils.h"

#define VERT_TEMPL "v %f %f %f"
#define NORM_TEMPL "vn %f %f %f"
#define TXCO_TEMPL "vt %f %f"
#define FACE_TEMPL "f %d//%d %d//%d %d//%d"
#define FACE_TEMPL_3VPF "f %d/%d/%d %d/%d/%d %d/%d/%d"
#define FACE_TEMPL_4VPF "f %d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d"

#define BUFFER_SIZE 512

WFImporter::WFImporter(QObject *parent) : QObject(parent)
{
}

model * WFImporter::read(QString filename)
{
    const char * c_name = filename.toStdString().c_str();
    FILE * fin = fopen(c_name, "r");
    char buffer[BUFFER_SIZE];

    float u, v, w;
    int face[12];
    face[11] = -1;

    verts.clear(); norms.clear(); txcos.clear();
    vinds.clear(); ninds.clear(); tinds.clear();

    while(fgets(buffer, BUFFER_SIZE, fin)) {
        if(sscanf(buffer, VERT_TEMPL, &u, &v, &w) == 3) {
            verts.push_back(u);
            verts.push_back(v);
            verts.push_back(w);
        } else if(sscanf(buffer, NORM_TEMPL, &u, &v, &w) == 3) {
            norms.push_back(u);
            norms.push_back(v);
            norms.push_back(w);
        } else if(sscanf(buffer, TXCO_TEMPL, &u, &v) == 2) {
            txcos.push_back(u);
            txcos.push_back(v);
        } else if(sscanf(buffer, FACE_TEMPL_4VPF,
                         &face[0], &face[1], &face[2],
                         &face[3], &face[4], &face[5],
                         &face[6], &face[7], &face[8],
                         &face[9], &face[10], &face[11]) == 12) {
            vinds.push_back(face[0]); tinds.push_back(face[1]); ninds.push_back(face[2]);
            vinds.push_back(face[3]); tinds.push_back(face[4]); ninds.push_back(face[5]);
            vinds.push_back(face[6]); tinds.push_back(face[7]); ninds.push_back(face[8]);
            vinds.push_back(face[9]); tinds.push_back(face[10]); ninds.push_back(face[11]);
        } else if(sscanf(buffer, FACE_TEMPL_3VPF,
                         &face[0], &face[1], &face[2],
                         &face[3], &face[4], &face[5],
                         &face[6], &face[7], &face[8]) == 9) {
            vinds.push_back(face[0]); tinds.push_back(face[1]); ninds.push_back(face[2]);
            vinds.push_back(face[3]); tinds.push_back(face[4]); ninds.push_back(face[5]);
            vinds.push_back(face[6]); tinds.push_back(face[7]); ninds.push_back(face[8]);
        } else if(sscanf(buffer, FACE_TEMPL,
                         &face[0], &face[1], &face[2], &face[3], &face[4], &face[5]) == 6) {
            vinds.push_back(face[0]); ninds.push_back(face[1]);
            vinds.push_back(face[2]); ninds.push_back(face[3]);
            vinds.push_back(face[4]); ninds.push_back(face[5]);
        }
    }
    fclose(fin);

    int vpf = 3;

    if(face[11] != -1) {
        vpf = 4;
    }

    return createModel(vpf);
}

model * WFImporter::createModel(int vpf) {
    model * result = new model();
    result->vpf = vpf;

    int count = verts.count();
    result->verts = (float *) malloc(sizeof(float) * count);
    for(int i = 0; i < count; i++) {
        result->verts[i] = verts.front();
        verts.pop_front();
    }

    count = norms.count();
    result->norms = (float *) malloc(sizeof(float) * count);
    for(int i = 0; i < count; i++) {
        result->norms[i] = norms.front();
        norms.pop_front();
    }

    count = txcos.count();
    result->txcos = (float *) malloc(sizeof(float) * count);
    for(int i = 0; i < count; i++) {
        result->txcos[i] = txcos.front();
        txcos.pop_front();
    }

    count = vinds.count();
    result->vind_count = count;
    result->vinds = (short *) malloc(sizeof(short) * count);
    for(int i = 0; i < count; i++) {
        result->vinds[i] = vinds.front() - 1;
        vinds.pop_front();
    }

    count = ninds.count();
    result->nind_count = count;
    result->ninds = (short *) malloc(sizeof(short) * count);
    for(int i = 0; i < count; i++) {
        result->ninds[i] = ninds.front() - 1;
        ninds.pop_front();
    }

    count = tinds.count();
    result->tind_count = count;
    result->tinds = (short *) malloc(sizeof(short) * count);
    for(int i = 0; i < count; i++) {
        result->tinds[i] = tinds.front() - 1;
        tinds.pop_front();
    }

    emit(importComplete(result));

    return result;
}
